/**
 * 统一API错误处理中心
 * 提供一致的错误分类、处理和用户反馈机制
 */

// 错误类型枚举
export const ERROR_TYPES = {
  AUTH_FAILED: 'AUTH_FAILED',           // 认证失败（401）
  PERMISSION_DENIED: 'PERMISSION_DENIED', // 权限不足（403）
  NOT_FOUND: 'NOT_FOUND',               // 资源不存在（404）
  SERVER_ERROR: 'SERVER_ERROR',         // 服务器错误（5xx）
  NETWORK_ERROR: 'NETWORK_ERROR',       // 网络错误
  TIMEOUT: 'TIMEOUT',                   // 请求超时
  VALIDATION_ERROR: 'VALIDATION_ERROR', // 验证错误（400）
  UNKNOWN: 'UNKNOWN'                    // 未知错误
}

// 错误处理状态
let retryQueue = []  // 待重试的请求队列
let isRefreshingToken = false  // 是否正在刷新token
let refreshSubscribers = []  // 等待token刷新的订阅者

/**
 * 统一API错误处理器
 */
export class ApiErrorHandler {
  /**
   * 处理API错误的主入口
   * @param {Error} error - Axios错误对象
   * @param {Object} router - Vue Router实例（可选）
   * @param {Object} authStore - 认证Store实例（可选）
   * @param {Object} config - 原始请求配置（用于重试）
   * @returns {Promise} 拒绝的Promise
   */
  static async handleError(error, router = null, authStore = null, config = null) {
    // 分类错误
    const errorType = this.classifyError(error)
    const errorMessage = this.getErrorMessage(error, errorType)
    
    // 记录错误日志
    this.logError(error, errorType)
    
    // 根据错误类型进行特定处理
    switch (errorType) {
      case ERROR_TYPES.AUTH_FAILED:
        return await this.handleAuthError(error, router, authStore, config)
      
      case ERROR_TYPES.PERMISSION_DENIED:
        return await this.handlePermissionError(error, router, authStore)
      
      case ERROR_TYPES.SERVER_ERROR:
        return await this.handleServerError(error, config)
      
      case ERROR_TYPES.NETWORK_ERROR:
      case ERROR_TYPES.TIMEOUT:
        return await this.handleNetworkError(error, config)
      
      case ERROR_TYPES.NOT_FOUND:
        return await this.handleNotFoundError(error, router)
      
      case ERROR_TYPES.VALIDATION_ERROR:
        return await this.handleValidationError(error)
      
      default:
        return await this.handleUnknownError(error)
    }
  }
  
  /**
   * 分类错误类型
   * @param {Error} error - 错误对象
   * @returns {string} 错误类型
   */
  static classifyError(error) {
    // 网络错误或请求未发出
    if (!error.response) {
      if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) {
        return ERROR_TYPES.TIMEOUT
      }
      return ERROR_TYPES.NETWORK_ERROR
    }
    
    const status = error.response.status
    
    // 根据HTTP状态码分类
    switch (status) {
      case 401:
        return ERROR_TYPES.AUTH_FAILED
      case 403:
        return ERROR_TYPES.PERMISSION_DENIED
      case 404:
        return ERROR_TYPES.NOT_FOUND
      case 400:
      case 422:
        return ERROR_TYPES.VALIDATION_ERROR
      case 500:
      case 502:
      case 503:
      case 504:
        return ERROR_TYPES.SERVER_ERROR
      default:
        return ERROR_TYPES.UNKNOWN
    }
  }
  
  /**
   * 获取友好的错误消息
   * @param {Error} error - 错误对象
   * @param {string} errorType - 错误类型
   * @returns {string} 友好的错误消息
   */
  static getErrorMessage(error, errorType) {
    // 优先使用后端返回的消息
    const serverMessage = error.response?.data?.message || error.response?.data?.error
    
    if (serverMessage) {
      return serverMessage
    }
    
    // 使用预定义的友好消息
    const defaultMessages = {
      [ERROR_TYPES.AUTH_FAILED]: '登录已过期，请重新登录',
      [ERROR_TYPES.PERMISSION_DENIED]: '您没有权限执行此操作',
      [ERROR_TYPES.NOT_FOUND]: '请求的资源不存在',
      [ERROR_TYPES.SERVER_ERROR]: '服务器出现错误，请稍后重试',
      [ERROR_TYPES.NETWORK_ERROR]: '网络连接失败，请检查您的网络',
      [ERROR_TYPES.TIMEOUT]: '请求超时，请重试',
      [ERROR_TYPES.VALIDATION_ERROR]: '提交的数据验证失败',
      [ERROR_TYPES.UNKNOWN]: '发生未知错误'
    }
    
    return defaultMessages[errorType] || error.message || '操作失败'
  }
  
  /**
   * 处理认证错误（401）
   */
  static async handleAuthError(error, router, authStore, originalConfig) {
    console.log('🔒 处理认证错误: 401 Unauthorized')
    
    // 如果正在刷新token，将请求加入队列
    if (isRefreshingToken) {
      return new Promise((resolve, reject) => {
        refreshSubscribers.push({ resolve, reject, config: originalConfig })
      })
    }
    
    // 如果已经是刷新token请求失败，直接登出
    if (originalConfig?.url?.includes('/auth/refresh')) {
      console.log('🔒 Token刷新失败，强制登出')
      this.forceLogout(router, authStore)
      return Promise.reject(error)
    }
    
    // 尝试刷新token
    isRefreshingToken = true
    
    try {
      // 动态导入AuthService避免循环依赖
      const { AuthService } = await import('../services/auth')
      await AuthService.refreshToken()
      
      console.log('✅ Token刷新成功')
      
      // 通知所有等待的请求
      this.onRefreshSuccess()
      
      // 重试原始请求
      if (originalConfig) {
        const axios = await import('axios')
        return axios.default.request(originalConfig)
      }
      
      return Promise.reject(error)
    } catch (refreshError) {
      console.log('❌ Token刷新失败')
      this.onRefreshFailure(refreshError)
      this.forceLogout(router, authStore)
      return Promise.reject(refreshError)
    } finally {
      isRefreshingToken = false
    }
  }
  
  /**
   * 处理权限错误（403）
   */
  static async handlePermissionError(error, router, authStore) {
    console.log('🚫 处理权限错误: 403 Forbidden')
    
    // 提取错误详情
    const errorDetails = {
      message: this.getErrorMessage(error, ERROR_TYPES.PERMISSION_DENIED),
      resource: error.config?.url || '',
      method: error.config?.method || ''
    }
    
    // 如果有authStore，记录权限错误
    if (authStore && authStore.setPermissionError) {
      authStore.setPermissionError({
        type: ERROR_TYPES.PERMISSION_DENIED,
        details: errorDetails,
        timestamp: new Date().toISOString()
      })
    }
    
    // 显示错误通知
    this.showErrorNotification(errorDetails.message, 'warning')
    
    // 如果有router，重定向到403页面
    if (router && router.currentRoute.value.path !== '/403') {
      router.push({
        path: '/403',
        query: {
          reason: 'PERMISSION_DENIED',
          resource: errorDetails.resource,
          from: router.currentRoute.value.path
        }
      })
    }
    
    return Promise.reject(error)
  }
  
  /**
   * 处理服务器错误（5xx）
   */
  static async handleServerError(error, originalConfig) {
    console.error('🔥 服务器错误:', error.response?.status)
    
    const message = this.getErrorMessage(error, ERROR_TYPES.SERVER_ERROR)
    this.showErrorNotification(message, 'error')
    
    // 服务器错误可以考虑重试（最多3次）
    if (this.shouldRetry(error) && (!originalConfig?._retryCount || originalConfig._retryCount < 3)) {
      console.log('🔄 准备重试请求...')
      return this.retryRequest(originalConfig)
    }
    
    return Promise.reject(error)
  }
  
  /**
   * 处理网络错误
   */
  static async handleNetworkError(error, originalConfig) {
    console.error('📡 网络错误:', error.message)
    
    const errorType = error.code === 'ECONNABORTED' ? ERROR_TYPES.TIMEOUT : ERROR_TYPES.NETWORK_ERROR
    const message = this.getErrorMessage(error, errorType)
    
    this.showErrorNotification(message, 'error')
    
    // 网络错误可以重试
    if (this.shouldRetry(error) && (!originalConfig?._retryCount || originalConfig._retryCount < 2)) {
      return this.retryRequest(originalConfig)
    }
    
    return Promise.reject(error)
  }
  
  /**
   * 处理404错误
   */
  static async handleNotFoundError(error, router) {
    console.warn('🔍 资源不存在: 404 Not Found')
    
    const message = this.getErrorMessage(error, ERROR_TYPES.NOT_FOUND)
    this.showErrorNotification(message, 'warning')
    
    return Promise.reject(error)
  }
  
  /**
   * 处理验证错误（400）
   */
  static async handleValidationError(error) {
    console.warn('⚠️ 验证错误:', error.response?.data)
    
    // 提取验证错误详情
    const validationErrors = error.response?.data?.errors || {}
    const message = this.getErrorMessage(error, ERROR_TYPES.VALIDATION_ERROR)
    
    // 如果有具体的字段错误，显示详细信息
    if (Object.keys(validationErrors).length > 0) {
      const errorMessages = Object.entries(validationErrors)
        .map(([field, errors]) => `${field}: ${Array.isArray(errors) ? errors.join(', ') : errors}`)
        .join('\n')
      
      this.showErrorNotification(`${message}\n${errorMessages}`, 'warning')
    } else {
      this.showErrorNotification(message, 'warning')
    }
    
    return Promise.reject(error)
  }
  
  /**
   * 处理未知错误
   */
  static async handleUnknownError(error) {
    console.error('❓ 未知错误:', error)
    
    const message = this.getErrorMessage(error, ERROR_TYPES.UNKNOWN)
    this.showErrorNotification(message, 'error')
    
    return Promise.reject(error)
  }
  
  /**
   * 判断是否应该重试
   * @param {Error} error - 错误对象
   * @returns {boolean}
   */
  static shouldRetry(error) {
    // 只重试特定的错误类型
    const retryableErrors = [
      ERROR_TYPES.NETWORK_ERROR,
      ERROR_TYPES.TIMEOUT,
      ERROR_TYPES.SERVER_ERROR
    ]
    
    const errorType = this.classifyError(error)
    return retryableErrors.includes(errorType)
  }
  
  /**
   * 重试请求
   * @param {Object} config - 原始请求配置
   * @returns {Promise}
   */
  static async retryRequest(config) {
    if (!config) {
      return Promise.reject(new Error('No config provided for retry'))
    }
    
    // 增加重试计数
    config._retryCount = (config._retryCount || 0) + 1
    
    // 延迟重试（指数退避）
    const delay = Math.min(1000 * Math.pow(2, config._retryCount - 1), 5000)
    console.log(`🔄 等待 ${delay}ms 后重试（第 ${config._retryCount} 次）`)
    
    await new Promise(resolve => setTimeout(resolve, delay))
    
    // 重新发起请求
    const axios = await import('axios')
    return axios.default.request(config)
  }
  
  /**
   * 强制登出
   */
  static forceLogout(router, authStore) {
    // 清除认证信息
    if (authStore && authStore.logout) {
      authStore.logout()
    } else {
      // 降级方案：直接清除localStorage
      localStorage.removeItem('token')
      localStorage.removeItem('user_info')
      localStorage.removeItem('auth')
    }
    
    // 重定向到登录页
    if (router) {
      router.push('/login')
    } else if (typeof window !== 'undefined') {
      window.location.href = '/login'
    }
  }
  
  /**
   * Token刷新成功回调
   */
  static onRefreshSuccess() {
    refreshSubscribers.forEach(({ resolve, config }) => {
      // 使用新token重试请求
      import('axios').then(axios => {
        resolve(axios.default.request(config))
      })
    })
    refreshSubscribers = []
  }
  
  /**
   * Token刷新失败回调
   */
  static onRefreshFailure(error) {
    refreshSubscribers.forEach(({ reject }) => {
      reject(error)
    })
    refreshSubscribers = []
  }
  
  /**
   * 显示错误通知
   * @param {string} message - 错误消息
   * @param {string} type - 通知类型（success, warning, error, info）
   */
  static showErrorNotification(message, type = 'error') {
    // 动态导入Element Plus避免循环依赖
    import('element-plus').then(({ ElMessage }) => {
      ElMessage({
        message,
        type,
        duration: 5000,
        showClose: true
      })
    }).catch(err => {
      // 降级方案：使用console
      console.error(`[${type.toUpperCase()}]`, message)
    })
  }
  
  /**
   * 记录错误日志
   * @param {Error} error - 错误对象
   * @param {string} errorType - 错误类型
   */
  static logError(error, errorType) {
    const logData = {
      type: errorType,
      status: error.response?.status,
      url: error.config?.url,
      method: error.config?.method,
      message: error.message,
      timestamp: new Date().toISOString()
    }
    
    // 开发环境详细日志
    if (process.env.NODE_ENV === 'development') {
      console.group(`🔴 API Error: ${errorType}`)
      console.error('Error Details:', logData)
      console.error('Full Error:', error)
      console.groupEnd()
    }
    
    // 生产环境可以发送到日志服务
    // 这里可以集成Sentry、LogRocket等服务
  }
  
  /**
   * 清除重试队列
   */
  static clearRetryQueue() {
    retryQueue = []
  }
  
  /**
   * 获取错误详情（用于调试）
   * @param {Error} error
   * @returns {Object}
   */
  static getErrorDetails(error) {
    return {
      type: this.classifyError(error),
      status: error.response?.status,
      statusText: error.response?.statusText,
      url: error.config?.url,
      method: error.config?.method,
      data: error.response?.data,
      message: error.message,
      code: error.code
    }
  }
}

// 默认导出
export default ApiErrorHandler

